iT邦幫忙

2023 iThome 鐵人賽

DAY 5
0
Modern Web

就是個Go,我也可以啦!GOGO系列 第 5

2023鐵人賽Day 5 Go X 方法

  • 分享至 

  • xImage
  •  

可能會遇到的雷點

  • 若函數傳參數事傳值的方式,則無法修改參數的原有值
  • 左大括號“{”不能單獨放一行
  • Go不允許function裡面再包function
  • 對defer延遲執行的函數,他的參數會在聲明時後就會求出具體值,而不是在執行時才求值
  • 對defer延遲執行的函數,會在調用他的函數結束時執行,而不是在調用他的作用域結束時執行

基本篇

func foo(a, b int)(mul int, div int){
  mul =  a * b
  div = a / b
  return mul , div
}

函數定義

在上述代碼中,定義了一個名為foo的函數,它接受兩個整數型參數並返回兩個整數型結果。這個函數計算了兩個整數的乘積和商。

參數清單 (a, b int)

  • 參數清單定義了函數接受的參數。
  • 參數清單中的每個參數都由名稱和型別組成。例如,名稱ab,型別int
  • 若多個連續參數有相同的型別,可以使用參數簡寫法。在這個例子中,ab都是整數型,所以可以寫作a, b int,而不是a int, b int

回傳的型別 (mul int, div int)

  • 這部分定義了函數返回的結果型別。
  • 可以為回傳值指定名稱。在這個例子中,回傳值的名稱分別為muldiv
  • 聲明了返回值的名稱後,函數內部可以像使用普通變量那樣使用它們,並在return語句中省略。在這個例子中,直接返回了muldiv
  • 回傳型別也可以不取名,例如寫作(int, int)。在這種情況下,return語句必須明確指定要返回的值。

回傳變數指定名稱

使用命名返回值並顯式返回
  • 在這個例子中,我們為返回值命名並在return語句中明確地指定要返回的值
func add(a , b int)(result int){
  result = a+b
  return result
}
  • 返回值被命名為result。
  • 在return語句中,我們明確地返回了result變量的值
使用naked return
  • 在這個例子中,我們依然為返回值命名,但在return語句中省略了要返回的值
func add(a , b int)(result int){
  result = a+b
  return 
}
  • 由於使用了naked return,所以return語句中沒有指定要返回的值。在這種情況下,所有已命名的返回值會被自動返回。
  • naked return可以增加程式碼的簡潔性,但在複雜的函數中可能會讓程式碼的可讀性下降。因此,建議在簡單的函數中使用naked return。

接收多重回傳值

func param(a , b int)(a , b int){
  return a , b
}

c, d := param(1,2)

但也可以忽略某些值

_, d := param(1,2)

然而因為我們是使用 :=短變數宣告,故左邊一定要有實際變數,不能都是_

函數變數的作用範圍

  • 在函數繩及宣告的變數和參數都會成為函數的區域變數,只能在該函數的主體內使用該變數
  • 函數無法呼叫他的父函式的變數,若要存取,唯一方式就是透過參數去傳遞

參數不定函式

你的描述中提到了Go語言中不定參數的重要特性。下面我將整理並擴展一些細節:

不定參數函數

不定參數函數允許你傳遞任意數量的參數。這是通過在參數的類型前加上三個點...來達成的。

func sum(nums ...int) int {
  total := 0
  for _, num := range nums {
    total += num
  }
  return total
}
  • 這個函數接受任意數量的整數參數。
  • 在函數內部,這些參數作為一個整數切片nums來訪問。

三個點的作用

  1. 聲明不定參數函數: 如上所述,可以使用三個點來定義不定數量的參數。

  2. 解引用切片: 如果你有一個切片並且想將其元素作為不定參數傳遞給函數,你可以使用三個點。

    nums := []int{1, 2, 3}
    total := sum(nums...) // 傳遞切片的元素作為不定參數
    

一些細節

  • 不定參數必須放在函數參數列表的末尾。
  • 函數可以有不定數量的不定參數,但只能有一個,並且它必須是列表中的最後一個。
func printNumbers(n ...int) {
  for _, number := range n {
    fmt.Println(number)
  }
}

不定參數提供了一個強大的工具,使函數能夠以更靈活的方式操作數據,特別是當你不知道將要處理的數據量時。

進階篇

Go 中的 defer

在 Go 語言中,defer 關鍵字使得函數調用可以被延遲,直到包含該 defer 語句的函數即將結束時才執行。這通常用於進行清理操作,如關閉文件或釋放資源。

執行順序

  1. 當一個函數執行到 return 語句時,返回值已確定,但還沒有真正返回到調用函數。
  2. 在實際返回前,所有的 defer 語句都會按照先進後出(LIFO)的順序執行。
  3. 在所有的 defer 語句執行完畢後,函數才真正返回。

defer 與返回值

Go 的 return 語句並不是一個原子操作。其實,函數返回的具體步驟如下:

  1. 給返回值賦值。
  2. 執行所有的 defer 語句。
  3. 真正的返回操作。

因此,defer 語句中的函數能夠修改返回值,使得最終的函數返回值與原始賦值不同。

func example() (result int) {
  defer func() {
    result++
  }()
  return 0
}

在上述例子中,即使 return 0 已設置返回值為 0,由於 defer 中的函數增加了返回值,所以 example() 最終返回 1。

避免混淆

為了更好地理解 defer 與返回值的關係,可以將 return 語句視為三個獨立的步驟:

  1. 設置返回值。
  2. 執行 defer 函數。
  3. 空的 return 操作。

上一篇
2023鐵人賽Day 4 Go的DRY藝術 - 使用套件
下一篇
2023鐵人賽Day 6 Go X 介面
系列文
就是個Go,我也可以啦!GOGO30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 則留言

我要留言

立即登入留言